/*
 * Copyright 2011 The Rusted Roof, LLC.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package org.proteusframework.core.api.model;

/**
 * Standardized versioning mechanism used by plugin archetypes to define API versions.
 * <p/>
 * A normal version number MUST take the form X.Y.Z where X, Y, and Z are integers.
 * <p/>
 * <ul>
 * <li>X is the major version</li>
 * <li>Y is the minor version</li>
 * <li>Z is the patch version</li>
 * </ul>
 * <p/>
 * Each element MUST increase numerically. For instance: 1.9.0 < 1.10.0 < 1.11.0.
 *
 * @author Tacoma Four
 * @see <a href="http://semver.org/">Semantic Versioning</a>
 */
public interface IVersion
{
    /**
     * Major version.
     * <p/>
     * Major version X (X.y.z | X > 0) MUST be incremented if any <b>backwards <i>incompatible</i> public API</b>
     * functionality is introduced. It MAY include minor and patch level changes.
     *
     * @return Major version
     */
    int getMajor();

    /**
     * Minor version.
     * <p/>
     * Minor version Y (x.Y.z | x > 0) MUST be incremented if new, <b>backwards compatible public API</b> functionality
     * is introduced. It MAY be incremented if substantial new functionality or improvements are introduced within the
     * private code. It MAY include patch level changes.
     *
     * @return Minor version
     */
    int getMinor();

    /**
     * Patch level.
     * <p/>
     * Patch version Z (x.y.Z | x > 0) MUST be incremented if only <b>backwards compatible bug fixes</b> are
     * introduced. A bug fix is defined as an internal change that fixes incorrect behavior.
     * <p/>
     * A special version number MAY be denoted by appending an arbitrary string immediately following the patch version.
     * The string MUST be comprised of only alphanumerics plus dash [0-9A-Za-z-] and MUST begin with an alpha character
     * [A-Za-z]. Special versions satisfy but have a lower precedence than the associated normal version. Precedence
     * SHOULD be determined by lexicographic ASCII sort order. For instance: 1.0.0beta1 < 1.0.0beta2 < 1.0.0.
     *
     * @return Patch level
     */
    String getPatch();

    /**
     * Use this method instead of <code>equals()</code> to determine if one version is semantically compatible
     * with another version.
     * <p/>
     * Based on the definition of <a href="http://semver.org/">Semantic Versioning</a>, a MINOR increment
     * may include new, backwards compatible functionality. Consider version 1.0 that includes the sole method
     * <code>public int foo()</code>. Along comes version 1.1, that maintains the status quo on the <code>foo</code>
     * method, but adds a brand new method <code>public int bar()</code>.  Consider these results:
     * <p/>
     * Version 1.0 is <code>VersionCompatibility.Incompatible</code> with version 1.1 because the caller will expect
     * the version to support the new method <code>bar()</code>, which version 1.0 fails to define.
     * <p/>
     * Version 1.1 is <code>VersionCompatibility.Compatible</code> with version 1.0 because the caller is guaranteed
     * that 100% of the methods defined in version 1.0 exist in version 1.0.
     * <p/>
     * Finally, Version 1.x is always <code>VersionCompatibility.Incompatible</code> with version 2.x, since backwards
     * incompatible changes were introduced into the public API.
     * <p/>
     * In situations where the <code>IVersion</code> fails to define a minor version number, the compatibility check
     * will always return <code>VersionCompatibility.Undetermined</code>.
     * <p/>
     * Patch level is never considered when determining version compatibility.
     *
     * @param version Version to compare for semantic (API) compatibility
     * @return true, if the version are semantically (API) compatible
     */
    VersionCompatibility isVersionCompatible(IVersion version);
}
